home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / Sources / SLGrUtil.cpp < prev    next >
Encoding:
Text File  |  1996-04-25  |  11.2 KB  |  442 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLGrUtil.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef SLGRUTIL_H
  13. #include "SLGrUtil.h"
  14. #endif
  15.  
  16. #ifndef FWRECT_H
  17. #include "FWRect.h"
  18. #endif
  19.  
  20. #ifndef FWPOINT_H
  21. #include "FWPoint.h"
  22. #endif
  23.  
  24. #ifndef FWFXMATH_H
  25. #include "FWFxMath.h"
  26. #endif
  27.  
  28. #ifndef FWGRUTIL_H
  29. #include "FWGrUtil.h"
  30. #endif
  31.  
  32. #ifndef FWPRIDEB_H
  33. #include "FWPriDeb.h"
  34. #endif
  35.  
  36. #include <stdio.h>
  37.  
  38. #ifdef FW_BUILD_MAC
  39. #pragma segment FWGraphx_SLGrUtil
  40. #endif
  41.  
  42. //----------------------------------------------------------------------------------------
  43. //    FW_RegionCode
  44. //----------------------------------------------------------------------------------------
  45. //
  46. //     1001 (9)  | 0001 (1) | 0101 (5)
  47. //    --------------------------------
  48. //     1000 (8)  | 0000 (0) | 0100 (4)
  49. //    --------------------------------
  50. //     1010 (10) | 0010 (2) | 0110 (6)
  51. //
  52. short SL_API FW_RegionCode(const FW_SPoint& line, const FW_SRect& rect)
  53. {
  54.     // No try block necessary - Do not throw
  55.     short regionCode = 0;
  56.     if (line.x < rect.left)
  57.         regionCode = 0x0008;
  58.     else if (line.x > rect.right)
  59.         regionCode = 0x0004;
  60.     
  61.     if (line.y < rect.top)
  62.         regionCode |= 0x0001;
  63.     else if (line.y > rect.bottom)
  64.         regionCode |= 0x0002;
  65.         
  66.     return regionCode;
  67. }
  68.  
  69. //----------------------------------------------------------------------------------------
  70. // ::FW_HitTestLine
  71. //----------------------------------------------------------------------------------------
  72. //    Uses a modified Cohen-Suterland with midpoint subdivision. Here we don't try to clip but
  73. //    just to find if a line intersect a rectangle of size 2*tolerance
  74.  
  75. FW_Boolean SL_API FW_HitTestLine(const FW_SPoint& pt1, const FW_SPoint& pt2,
  76.                                 const FW_SPoint& test, FW_Fixed tolerance)
  77. {
  78.     // No try block necessary - Do not throw
  79.  
  80.     FW_CRect rect(test.x - tolerance,
  81.                 test.y - tolerance,
  82.                 test.x + tolerance,
  83.                 test.y + tolerance);
  84.     
  85.     short regionCode1, regionCode2, middleCode;
  86.     
  87.     if ((regionCode1 = FW_RegionCode(pt1, rect)) == 0)
  88.         return TRUE;        // start is inside the rectangle
  89.         
  90.     if ((regionCode2 = FW_RegionCode(pt2, rect)) == 0)
  91.         return TRUE;        // end is inside the rectangle
  92.         
  93.     if ((regionCode1 & regionCode2) != 0)
  94.         return FALSE;        // line totally outside
  95.     
  96.     FW_CPoint h1(pt1), h2(pt2);
  97.     FW_CPoint middle(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
  98.  
  99.     while (middle != h1 || middle != h2)
  100.     {
  101.         if ((middleCode = FW_RegionCode(middle, rect)) == 0)
  102.             return TRUE;    // middle is in the rectangle
  103.             
  104.         if ((middleCode & regionCode1) != 0)
  105.         {
  106.             // line (middle, h1) outside the rectangle 
  107.             h1 = middle;
  108.             regionCode1 = middleCode;
  109.         }
  110.         else
  111.         {
  112.             // line (h2, middle) outside the rectangle 
  113.             h2 = middle;
  114.             regionCode2 = middleCode;
  115.         }
  116.         
  117.         if ((regionCode1 & regionCode2) != 0)        
  118.             return FALSE;    // line (h1, h2) totally outside
  119.                  
  120.         middle.Set(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
  121.     }
  122.     
  123.     return FALSE;
  124. }
  125.  
  126. //----------------------------------------------------------------------------------------
  127. //    FW_HitTestPolygon
  128. //
  129. //    Crossings algorithm, Graphics Gems IV, article I.4
  130. //----------------------------------------------------------------------------------------
  131.  
  132. static FW_Fixed XIntersect(const FW_SPoint* vtx0, const FW_SPoint* vtx1, FW_Fixed ty)
  133. {
  134.     return vtx1->x - FW_WideMultiply(vtx1->y - ty, vtx0->x - vtx1->x) / (vtx0->y - vtx1->y);
  135. }
  136.  
  137. FW_Boolean SL_API FW_HitTestPolygon(long pointCount, const FW_SPoint* points, const FW_SPoint& point)
  138. {
  139.     // No try block necessary - Do not throw
  140.  
  141.     FW_Boolean yFlag0, yFlag1, isInside = FALSE, xFlag0;
  142.  
  143.     FW_Fixed tx = point.x;
  144.     FW_Fixed ty = point.y;
  145.  
  146.     const FW_SPoint* vtx0 = points + pointCount - 1;
  147.     const FW_SPoint* vtx1 = points;
  148.  
  149.     yFlag0 = vtx0->y >= ty;
  150.  
  151.     for(long j = 0; j < pointCount; j ++)
  152.     {
  153.         yFlag1 = vtx1->y >= ty;
  154.  
  155.         if(yFlag1 != yFlag0)
  156.         {
  157.             xFlag0 = vtx0->x >= tx;
  158.  
  159.             if(xFlag0 == (vtx1->x >= tx))
  160.             {
  161.                 if(xFlag0)
  162.                     isInside = !isInside;
  163.             }
  164.             else
  165.             {
  166.                 if(::XIntersect(vtx0, vtx1, ty) >= tx)
  167.                     isInside = !isInside;
  168.             }
  169.         }
  170.  
  171.         yFlag0 = yFlag1;
  172.         vtx0 = vtx1;
  173.         vtx1 ++;
  174.     }
  175.  
  176.     return isInside;
  177. }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. //    FW_PtInOval
  181. //----------------------------------------------------------------------------------------
  182.  
  183. FW_Boolean SL_API FW_PtInOval(const FW_SRect& ovalRect, const FW_SPoint& test)
  184. {
  185.     // No try block necessary - Do not throw
  186.  
  187.     // A brief refresher in fifth-grade geometry:
  188.     
  189.     // An ellipse (not an oval!) is defined as a set of points such as:
  190.     //    (x - x0/a)^2 + (y - y0/b)^2 <= 1, where:
  191.     //    <x0, y0> is the center of the ellipse
  192.     //    a is the x-radius and b is the y-radius
  193.  
  194.     // It is possible to get rid of division by evaluating
  195.     //    (bx)^2 + (ay)^2 <= a^2 * b^2, but this can overflow real easy
  196.  
  197.     FW_CRect Oval = ovalRect;
  198.     if(Oval.Contains(test))
  199.     {
  200.         // Adjust center by 0.5 because of rounding
  201.         FW_Fixed xMiddle = FW_Half(ovalRect.left + ovalRect.right  - FW_kFixedPos1);
  202.         FW_Fixed yMiddle = FW_Half(ovalRect.top  + ovalRect.bottom - FW_kFixedPos1);
  203.  
  204.         FW_Fixed a = FW_Half(ovalRect.right - ovalRect.left);
  205.         FW_Fixed b = FW_Half(ovalRect.bottom - ovalRect.top);
  206.         
  207.         FW_Fixed xa = (test.x - xMiddle) / a;
  208.         xa *= xa;
  209.         
  210.         FW_Fixed xb = (test.y - yMiddle) / b;
  211.         xb *= xb;
  212.         
  213.         return xa + xb <= FW_IntToFixed(1);
  214.     }
  215.  
  216.     return FALSE;
  217. }
  218.  
  219. //----------------------------------------------------------------------------------------
  220. //    FW_PtInRoundRect
  221. //----------------------------------------------------------------------------------------
  222.  
  223. FW_Boolean SL_API FW_PtInRoundRect(const FW_SRect& rect, const FW_SPoint& ovalSize, const FW_SPoint& test)
  224. {
  225.     // No try block necessary - Do not throw
  226.  
  227.     FW_CRect r = rect;
  228.     if(r.Contains(test))
  229.     {
  230.         // Find out if the test point may be inside of one of four corner ovals
  231.     
  232.         FW_CRect rectOval;
  233.  
  234.         FW_Fixed halfX = FW_Half(ovalSize.x);
  235.         FW_Fixed halfY = FW_Half(ovalSize.y);
  236.  
  237.         if(test.x < rect.left + halfX)
  238.         {
  239.             // Top-left and bottom-left ovals
  240.             rectOval.left = rect.left;
  241.             rectOval.right = rect.left + ovalSize.x;
  242.         }
  243.         else if(test.x > rect.right - halfX)
  244.         {
  245.             // Top-right and bottom-right ovals
  246.             rectOval.left = rect.right - ovalSize.x;
  247.             rectOval.right = rect.right;
  248.         }
  249.  
  250.         if(test.y < rect.top + halfY)
  251.         {
  252.             // Top-left and top-right
  253.             rectOval.top = rect.top;
  254.             rectOval.bottom = rect.top + ovalSize.y;
  255.         }
  256.         else if(test.y > rect.bottom - halfY)
  257.         {
  258.             // Bottom-left and bottom-right ovals
  259.             rectOval.top = rect.bottom - ovalSize.y;
  260.             rectOval.bottom = rect.bottom;
  261.         }
  262.  
  263.         if(rectOval.IsEmpty())
  264.             return TRUE;
  265.  
  266.         return ::FW_PtInOval(rectOval, test);
  267.     }
  268.  
  269.     return FALSE;
  270. }
  271.  
  272. #ifdef FW_DEBUG
  273. //----------------------------------------------------------------------------------------
  274. // ::Priv_FormatPoint
  275. //----------------------------------------------------------------------------------------
  276.  
  277. static void Priv_FormatPoint(char *s, const char* prompt, const FW_SPoint& point)
  278. {
  279.     sprintf(s, "%s X: %f Y: %f", prompt, FW_FixedToDouble(point.x), FW_FixedToDouble(point.y));
  280. }
  281. #endif
  282.  
  283. #ifdef FW_DEBUG
  284. //----------------------------------------------------------------------------------------
  285. // ::Priv_FormatRect
  286. //----------------------------------------------------------------------------------------
  287.  
  288. static void Priv_FormatRect(char *s, const char* prompt, const FW_SRect& rect)
  289. {
  290.     sprintf(s, "%s left: %f top: %f right: %f bottom: %f",
  291.                 prompt, 
  292.                 FW_FixedToDouble(rect.left), 
  293.                 FW_FixedToDouble(rect.top),
  294.                 FW_FixedToDouble(rect.right), 
  295.                 FW_FixedToDouble(rect.bottom));
  296. }
  297. #endif
  298.  
  299. //----------------------------------------------------------------------------------------
  300. // ::FW_LogPoint
  301. //----------------------------------------------------------------------------------------
  302.  
  303. FW_EXPORT void SL_API FW_LogPoint(Environment* ev, const char* prompt, const FW_SPoint& point)
  304. {
  305.     // No try block necessary - Do not throw
  306. FW_UNUSED(ev);
  307. #ifdef FW_DEBUG
  308.     char s[255];
  309.     Priv_FormatPoint(s, prompt, point);
  310.     FW_CDebugConsole::LogMessage(s);
  311. #endif
  312. }
  313.  
  314. //----------------------------------------------------------------------------------------
  315. // ::FW_LogRect
  316. //----------------------------------------------------------------------------------------
  317.  
  318. FW_EXPORT void SL_API FW_LogRect(Environment* ev, const char* prompt, const FW_SRect& rect)
  319. {
  320.     // No try block necessary - Do not throw
  321. FW_UNUSED(ev);
  322. #ifdef FW_DEBUG
  323.     char s[255];
  324.     Priv_FormatRect(s, prompt, rect);
  325.     FW_CDebugConsole::LogMessage(s);
  326. #endif
  327. }
  328.  
  329. //----------------------------------------------------------------------------------------
  330. // ::FW_LogShape
  331. //----------------------------------------------------------------------------------------
  332.  
  333. FW_EXPORT void SL_API FW_LogShape(Environment* ev, const char* prompt, ODShape* shape)
  334. {
  335.     // No try block necessary - Do not throw
  336. #ifdef FW_DEBUG
  337.     FW_CRect rect;
  338.     shape->GetBoundingBox(ev, (ODRect*) &rect);
  339.     FW_LogRect(ev, prompt, rect);
  340. #endif
  341. }
  342.  
  343. //----------------------------------------------------------------------------------------
  344. // ::FW_LogTransform
  345. //----------------------------------------------------------------------------------------
  346.  
  347. FW_EXPORT void SL_API FW_LogTransform(Environment* ev, const char* prompt, ODTransform* transform)
  348. {
  349.     // No try block necessary - Do not throw
  350. #ifdef FW_DEBUG
  351.     FW_CPoint ptScale;
  352.     transform->GetScale(ev, (ODPoint*) &ptScale);
  353.  
  354.     FW_CPoint ptOffset;
  355.     transform->GetOffset(ev, (ODPoint*) &ptOffset);
  356.  
  357.     char s[128];
  358.     ::sprintf(s,
  359.         "xform: %s: pt * [%.2f, %.2f] + [%.2f, %.2f]\n",
  360.         prompt,
  361.         FW_FixedToDouble(ptScale.x),            FW_FixedToDouble(ptScale.y),
  362.         FW_FixedToDouble(ptOffset.x),            FW_FixedToDouble(ptOffset.y)
  363.     );
  364.     FW_CDebugConsole::LogMessage(s);
  365. #endif
  366. }
  367.  
  368. /*
  369. #ifdef FW_BUILD_MAC
  370. //----------------------------------------------------------------------------------------
  371. // ::FW_PrivMacShowColorTable
  372. //----------------------------------------------------------------------------------------
  373.  
  374. void SL_API FW_PrivMacShowColorTable(CTabHandle cth)
  375. {
  376. #ifdef FW_DEBUG
  377.     if (cth == NULL)
  378.         return;
  379.  
  380.     short nColors = (*cth)->ctSize + 1;
  381.  
  382.     short cellSize;
  383.     short xCount, yCount;
  384.     
  385.     if (nColors == 256)
  386.     {
  387.         cellSize = 30;
  388.         xCount = 16;
  389.         yCount = 16;
  390.     }
  391.     else
  392.     {
  393.         cellSize = 50;
  394.         xCount = 4;
  395.         yCount = nColors / xCount;
  396.     }
  397.     
  398.     GDHandle gd = ::GetMainDevice();
  399.     if ((*gd)->gdNextGD != NULL)
  400.         gd = (GDHandle) (*gd)->gdNextGD;
  401.  
  402.     PixMapHandle pmh = (*gd)->gdPMap;
  403.  
  404.     Rect rect;
  405.     rect.left    = (*pmh)->bounds.left + 50;
  406.     rect.top    = (*pmh)->bounds.top + 50;
  407.     rect.right    = rect.left + cellSize * xCount;
  408.     rect.bottom = rect.top + cellSize * yCount;
  409.  
  410.     WindowPtr window = ::NewCWindow(NULL, &rect, "\pColor table", TRUE,
  411.         noGrowDocProc, (WindowPtr) -1L, FALSE, 0);
  412.  
  413.     if (window != NULL)
  414.     {
  415.         FW_CMacTempPort port = window;
  416.         
  417.         short nCurColor = 0;
  418.         for (short xColor = 0; xColor < xCount; ++ xColor)
  419.         {
  420.             for (short yColor = 0; yColor < yCount; ++ yColor)
  421.             {
  422.                 ::RGBBackColor(&(*cth)->ctTable[nCurColor].rgb);
  423.  
  424.                 Rect cell;
  425.                 cell.left    = xColor * cellSize;
  426.                 cell.top    = yColor * cellSize;
  427.                 cell.right    = cell.left + cellSize;
  428.                 cell.bottom    = cell.top + cellSize;
  429.                 ::EraseRect(&cell);
  430.                 
  431.                 ++ nCurColor;
  432.             }
  433.         }
  434.     }
  435.     
  436.     if (window != NULL)
  437.         ::DisposeWindow(window);
  438. #endif
  439. }
  440. #endif
  441. */
  442.